//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.

#include <osgUtil/RenderGraph>

#include <map>
#include <vector>
#include <string>

// forward declare Statistics to remove link dependancy.
namespace osg { class Statistics; }

class RenderStage;

/**
 * RenderBin base class.
 */
class RenderBin : public osg::Object
{
    public:
    
        typedef std::vector<RenderLeaf*>                    RenderLeafList; 
        typedef std::vector<RenderGraph*>                   RenderGraphList;
        typedef std::map< int, osg::ref_ptr<RenderBin> >    RenderBinList; 

        // static methods.
        static RenderBin* createRenderBin(const std::string& binName);
        static void addRenderBinPrototype(RenderBin* proto);
        static void removeRenderBinPrototype(RenderBin* proto);


        RenderBin();

        virtual osg::Object* cloneType() const { return new RenderBin(); }
        virtual osg::Object* clone(const osg::CopyOp&) const { return new RenderBin(); } // note only implements a clone of type.
        virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const RenderBin*>(obj)!=0L; }
        virtual const char* libraryName() const { return "osgUtil"; }
        virtual const char* className() const { return "RenderBin"; }

        virtual void reset();
        
        RenderBin* find_or_insert(int binNum,const std::string& binName);

        void addRenderGraph(RenderGraph* rg)
        {
            _renderGraphList.push_back(rg);
        }


        void sort();

        virtual void sort_local();

        virtual void draw(osg::State& state,RenderLeaf*& previous);

        virtual void draw_local(osg::State& state,RenderLeaf*& previous);

        /** extract stats for current draw list. */
        bool getStats(osg::Statistics* primStats);
        void getPrims(osg::Statistics* primStats);
        bool getPrims(osg::Statistics* primStats, const int nbin);


    public:

   
        int             _binNum;
        RenderBin*      _parent;
        RenderStage*    _stage;
        RenderBinList   _bins;
        RenderGraphList _renderGraphList;
        RenderLeafList  _renderLeafList;
           
        typedef std::map< std::string, osg::ref_ptr<RenderBin> > RenderBinPrototypeList;
        static RenderBinPrototypeList s_renderBinPrototypeList;
        
    protected:
    
        virtual ~RenderBin();

};

/** Proxy class for automatic registration of renderbins with the RenderBin prototypelist.*/
template<class T>
class RegisterRenderBinProxy
{
    public:
        RegisterRenderBinProxy()
        {
            _rb = new T;
            RenderBin::addRenderBinPrototype(_rb.get());
        }

        ~RegisterRenderBinProxy()
        {
            RenderBin::removeRenderBinPrototype(_rb.get());
        }
        
    protected:
        osg::ref_ptr<T> _rb;
};

